/**
*
*/
package org.javacommerce.paypal.validation;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.javacommerce.core.config.JavaCommerce;
import org.javacommerce.core.log.LogMessage;
import org.javacommerce.core.log.LogMessageFactory;
import org.javacommerce.paypal.PayPalValidationException;
/**
* Abstract PayPal Validation class. This is the base for all PayPal Validations.
*
* This class can be extended to implement various PayPal Notification Schemes (such as IPN
* or PDT). The base class builds the data to post back to PayPal for validation, posts the
* data, and verifies the response is expected.
*
* <h3>CONFIGURATION<h3>
* <ul>
* <li>paypal.encoding: Encoding scheme to use when building Strings. Much match what what the
* PayPal account is cofigured for.
* </ul>
* @author Michael Blanton (mike@mikeblanton.com)
*/
public abstract class AbstractValidation {
protected static final String PARAM_CMD = "cmd";
private static final String CONTENT_TYPE = "text/html";
private static final Log LOG = LogFactory.getLog(AbstractValidation.class);
private static final LogMessage LOGM = LogMessageFactory.getInstance();
/**
* Encoding scheme to use with PayPal. Much match what the PayPal account is configured for.
*/
private static final String CONFIG_ENCODING = "paypal.encoding";
private static final String DEFAULT_ENCODING = JavaCommerce.DEFAULT_ENCODING;
public static final String ENCODING = JavaCommerce.getConfiguration().getString(CONFIG_ENCODING, DEFAULT_ENCODING);
/**
* Validate the passed HttpServletRequest with PayPal. Post the response, reset the
* reader so it can be used later.
* @param _request
* @throws UnsupportedEncodingException
* @throws IOException
* @throws PayPalValidationException Thrown if the validation does not return the expected result.
*/
public final String[] verifyHttpRequest(HttpServletRequest _request) throws UnsupportedEncodingException, IOException, PayPalValidationException {
long startTime = System.currentTimeMillis();
HttpClient client = new HttpClient();
PostMethod post = new PostMethod(getURL());
if (LOG.isDebugEnabled()) {
LOG.debug("Building HttpClient to URL [" + getURL() + "]");
}
getPostData(_request, post);
if (LOG.isDebugEnabled()) {
LOG.debug("Executing method");
}
client.executeMethod(post);
BufferedReader reader = new BufferedReader(new InputStreamReader(post.getResponseBodyAsStream()));
String response = reader.readLine();
if (LOG.isDebugEnabled()) {
LOG.debug("Response: [" + response + "]");
}
if (!response.equals(getVerifiedText())) {
long endTime = System.currentTimeMillis();
LOGM.logFailure("AbstractValidation.verifyHttpRequest", startTime, endTime, response);
throw new PayPalValidationException("Error validating response from PayPal", response, post.getStatusCode());
}
ArrayList<String> respList = new ArrayList<String>();
respList.add(response);
while ((response = reader.readLine()) != null) {
respList.add(response);
}
long endTime = System.currentTimeMillis();
LOGM.logSuccess("AbstractValidation.verifyHttpRequest", startTime, endTime);
return (String[]) respList.toArray(new String[respList.size()]);
}
/**
* Build the POST data for validation, appending the Command (cmd) as appropriate.
* This method can be overidden if additional information needs to be appended.
* @param _request
* @return java.util.List instance containing name=value pairs from the post.
* @throws IOException Thrown if there is a problem reading the request.
*/
protected void getPostData(HttpServletRequest _request, PostMethod _method) throws IOException {
Enumeration names = _request.getParameterNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
String value = _request.getParameter(name);
NameValuePair pair = new NameValuePair(name, value);
if (LOG.isDebugEnabled()) {
LOG.debug("Read [" + pair.toString() + "]");
}
_method.addParameter(pair);
}
NameValuePair cmd = new NameValuePair(PARAM_CMD, getCommand());
if (LOG.isDebugEnabled()) {
LOG.debug("Added [" + cmd.toString() + "]");
}
_method.addParameter(cmd);
}
/**
* Content Type to use. Can be overidden if defaults aren't wanted.
* @return
*/
protected String getContentType() {
return CONTENT_TYPE;
}
public abstract String getURL();
public abstract String getVerifiedText();
public abstract String getCommand();
}